﻿#include "Monitor.h"
#include <QtMath>

Monitor::Monitor()
{

}

Monitor::~Monitor()
{

}

//执行动作,暂时没有用
void Monitor::execute(QList<Performer *> execute_compo)
{
    /*
    foreach(Performer *execute_c, execute_compo)
    {
        execute_c->execute();
    }
    execute_compo.clear();
    */
}

//指挥
void Monitor::command(QList<Performer*> active_compo, QList<Performer*> passive_compo)
{
    foreach(Performer *active, active_compo)
    {
        foreach(Performer *passive, passive_compo)
        {
            if(active == passive)
            {   continue;   }
            Position position = this->check(passive->getShape(), passive->getSite(),
                                            active->getShape(),  active->getSite());
        }
    }
}

//位置判断
Position Monitor::check(const Shape &fix, const VPoint &fix_site,
                        const Shape &shift, const VPoint &shift_site)
{
    if(fix.getPoints().length() <= 1)
    {
        if(fix.getRadius() < shift.getRadius())
        {
            Position &position = this->checkPoint(shift_site, shift.getRadius(), fix_site, fix.getRadius());
            position.direction.setAngle(position.direction.angle() + M_PI);
            return position;
        }
        else
        {
            return this->checkPoint(fix_site, fix.getRadius(), shift_site, shift.getRadius());
        }
    }
    else
    {
        VPoint po_fs = shift_site - fix_site;

        VPoint po_a = fix.getPoints().first();
        VPoint po_b = fix.getPoints().last();

        for(int i = fix.getPoints().length() - 1; i > 0; --i)
        {
            if(po_fs.angle() > fix.getPoints().at(i).angle() &&
               po_fs.angle() < fix.getPoints().at(i - 1).angle())
            {
                po_a = fix.getPoints().at(i);
                po_b = fix.getPoints().at(i - 1);
            }
        }

        return this->checkLine(po_a, po_b, fix.getRadius(), po_fs, shift.getRadius());
    }
}

//判断点
Position Monitor::checkPoint(const VPoint &po_fix, double r_fix, const VPoint &po_shift, double r_shift)
{
    Position position;
    position.direction = po_fix - po_shift;
    position.relative = (position.direction.length() - r_fix) / r_shift;
    if(position.relative < 0)
    {
        position.direction = po_shift - po_fix;
    }
    return position;
}

//判断线
Position Monitor::checkLine(const VPoint &po_fix_a, const VPoint &po_fix_b, double r_fix,
                            const VPoint &po_shift, double r_shift)
{//以(0,0)为多边形判断原点,因此无需取用
    VPoint po_as = po_shift - po_fix_a;
    VPoint po_bs = po_shift - po_fix_b;
    VPoint po_ab = po_fix_b - po_fix_a;

    double bas =  qCos(po_as.angle() - po_ab.angle());
    double abs =  qCos(po_bs.angle() - po_ab.angle());

    if(bas < 0)
    {
        return this->checkPoint(po_fix_a, r_fix, po_shift, r_shift);
    }
    else if(abs > 0)
    {
        return this->checkPoint(po_fix_b, r_fix, po_shift, r_shift);
    }
    else
    {
        double oa_ln = po_fix_a.length() * qAbs(qSin(po_fix_a.angle() - po_ab.angle()));
        double os_ln = po_shift.length() * qAbs(qSin(po_shift.angle() - po_ab.angle()));

        Position position;
        position.direction = po_ab;
        position.direction.setLength(bas * po_as.length());
        position.direction -= po_as;
        position.relative = (os_ln - oa_ln - r_fix) / r_shift;
        return position;
    }
}
